#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>

#define BUF_SIZE	500000 // Max buffer size 500KB
#define LISTEN_PORT	60000

int main() {
	int sock_listen, i, sock_rcv, addr_size, size, pos = 0;
	char buf_recv[BUF_SIZE], buf_send[BUF_SIZE], fileName[50] = "", *pch,
		bad_response[1000], good_response[500], current_time[80];
	struct sockaddr_in my_addr, recv_addr;
	FILE *fp, *fpIndex;
	
	// Get the current time
	struct tm *timeinfo;
	time_t raw_time;
	time (&raw_time);
	timeinfo = localtime (&raw_time);
	strftime (current_time, 80, "%a, %e %b %G %H:%M:%S %Z", timeinfo);
	snprintf(bad_response, 1000, "HTTP/1.1 404 Not Found\r\n"
			"Date: %s\r\n"
			"Server: CSCE3530\r\n"
			"Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"
			"<html>"
			"<head>"
			"<title>"
			"404 - Not Found"
			"</title>"
			"<link href=\"http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css\" rel=\"stylesheet\">"
			"<body>"
			"<div class=\"col-md-4 col-md-offset-4\" style=\"padding-top: 10%;\">"
			"<div class=\"panel panel-default\">"
			"<div class=\"panel-heading\">"
			"<h3 class=\"panel-title\" style=\"text-align: center; font-weight: bold;\">404 - Not Found</h3>"
			"</div>"
			"<div class=\"panel-body text-center\">"
			"<img src=\"404.png\">"
			"<h2>Sorry, your file was not found.</h2>"
			"</div>"
			"</div>"
			"</div>"
			"</body>"
			"</head>"
			"</html>", current_time);
	snprintf(good_response, 500, "HTTP/1.1 200 OK\r\n"
			"Date: %s\r\n"
			"Last-Modified: Fri, 10 Oct 2014 17:00:02 GMT\r\n"
			"Accept-Ranges: bytes\r\n"
			"Server: CSCE3530\r\n"
			"Content-Type: text/html; charset=UTF-8\r\n\r\n", current_time);
	
	// Create socket
	sock_listen = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (sock_listen < 0) {
		printf("Error: Could not connect to socket\n");
		exit(0);
	}

	// Create local address structure
	memset(&my_addr, '0', sizeof(my_addr));
	my_addr.sin_family = AF_INET;
	my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	my_addr.sin_port = htons((unsigned short) LISTEN_PORT);

	// Bind the socket, obtaining the IP and PORT
	i = bind(sock_listen, (struct sockaddr*) &my_addr, sizeof(my_addr));

	if (i < 0) {
		printf("Binding to port %d failed.\nIt must be in use by another program.\n", LISTEN_PORT);
		exit(0);
	}

	// Await communication from a client
	i = listen(sock_listen, 5);
	if (i < 0)
		printf("Listen failed\n");
	else printf("Server started successfully\n");
	
	// Get new socket to receive data on and accept connection from client
	addr_size = sizeof(recv_addr);

	while(1) {
		sock_rcv = accept(sock_listen, (struct sockaddr *) &recv_addr, &addr_size);
		// Receive HTTP header from client
		printf("Waiting for client...\n\n");
		recv(sock_rcv, buf_recv, BUF_SIZE, 0);
		printf("%s", buf_recv); // buf_recv stores the HTTP header
		
		// Parse HTTP header for the filename in GET
		pch = strchr(buf_recv,'/');
		pch = pch+1;
		
		if (isspace(*pch)) {
			printf("Loading index.html\n\n");
			fpIndex = fopen("index.html", "rb");
			fseek(fpIndex, 0, SEEK_END);
			size = ftell(fpIndex);
			rewind(fpIndex);
			fread(buf_send, 1, size, fpIndex);
			// Send an HTTP response
			send(sock_rcv, good_response, strlen(good_response), 0);
			send(sock_rcv, buf_send, size, 0);
			fclose(fpIndex);
		}
		else {
			while (!isspace(*pch)) {
				fileName[pos] = *pch;
				pch++;
				pos++;
			}
			pos = 0; // Reset pos

			// Once the filename is found, open it on the server. If it
			// returns NULL, the file does not exist. If the file does exist then
			// store the file contents into BUFFER and send it to the client
			
			// Open the file on the server
			fp = fopen(fileName, "rb");

			// If the file does not exist on server
			if (fp == NULL) {
				printf("%s does not exist\nSending 404 page\n\n", fileName);
				send(sock_rcv, bad_response, strlen(bad_response), 0);
			}
			else {
				printf("Sending %s ", fileName);
				fseek(fp, 0, SEEK_END);
				size = ftell(fp);
				printf("[%d bytes] to client\n\n", size);
				rewind(fp); // Reset the file pointer
				// Load the file into buffer
				fread(buf_send, 1, size, fp);
				// Send the HTTP response
				send(sock_rcv, good_response, strlen(good_response), 0);
				// Send the buffer to the client so the client can
				// create a copy of the file from buffer
				send(sock_rcv, buf_send, size, 0);
				fclose(fp); // Close the file since we are done reading it
			}
		}
		close(sock_rcv);
		memset(fileName, 0, strlen(fileName)); // Clear the filename for the next one
	}
	return 0;
}